package com.ywy.bootadmin.service.sys.impl;

import com.ywy.bootadmin.common.enums.TaskStatusEnum;
import com.ywy.bootadmin.common.rest.BaseResult;
import com.ywy.bootadmin.common.rest.PageResult;
import com.ywy.bootadmin.common.rest.ResponseCode;
import com.ywy.bootadmin.dao.sys.TaskDao;
import com.ywy.bootadmin.model.sys.Task;
import com.ywy.bootadmin.service.sys.TaskService;
import com.ywy.bootadmin.task.QuartzManager;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 定时任务Service实现
 *
 * @author ywy
 * @date 2022/1/7 16:38
 */
@Service
@Transactional
public class TaskServiceImpl implements TaskService {
    @Autowired
    private TaskDao taskDao;
    @Autowired
    private QuartzManager quartzManager;

    @Override
    public BaseResult listByPage(Integer offset, Integer limit, Map<String, Object> params) {
        Integer count = taskDao.count(params);
        List<Task> userList = taskDao.listByPage(offset, limit, params);
        PageResult<Task> result = new PageResult<>();
        result.setTotal(count);
        result.setDatas(userList);
        return new BaseResult(result);
    }

    @Override
    public Task getById(Integer id) {
        return taskDao.getById(id);
    }

    @Override
    public BaseResult save(Task task) {
        task.setJobStatus(TaskStatusEnum.STOP.getCode());
        Integer count = taskDao.save(task);
        if (count > 0) {
            return new BaseResult();
        }
        return new BaseResult(ResponseCode.SAVE_ERROR);
    }

    @Override
    public BaseResult update(Task task) {
        Task task2 = taskDao.getById(task.getId());
        // 如果修改任务，且任务状态为运行则不能修改
        if (TaskStatusEnum.RUNNING.getCode() ==  task2.getJobStatus()) {
            return new BaseResult(ResponseCode.STOP_TASK_BEFORE_OPERATING);
        }
        Integer count = taskDao.update(task);
        if (count > 0) {
            return new BaseResult();
        }
        return new BaseResult(ResponseCode.UPDATE_ERROR);
    }

    @Override
    public BaseResult delete(Integer id) {
        Task task = taskDao.getById(id);
        if (task == null) {
            return new BaseResult(ResponseCode.DELETE_ERROR);
        }
        if (TaskStatusEnum.RUNNING.getCode() == task.getJobStatus()) {
            return new BaseResult(ResponseCode.STOP_TASK_BEFORE_OPERATING);
        }
        try {
            quartzManager.deleteJob(task);
            taskDao.delete(id);
            return new BaseResult();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return new BaseResult(ResponseCode.DELETE_ERROR);
    }

    @Override
    public BaseResult batchDelete(Integer[] ids) {
        // 判断任务是否都停止
        List<Task> taskList = new ArrayList<>();
        for (Integer id : ids) {
            Task task = taskDao.getById(id);
            if (TaskStatusEnum.RUNNING.getCode() == task.getJobStatus()) {
                return new BaseResult(ResponseCode.STOP_TASK_BEFORE_OPERATING);
            }
            taskList.add(task);
        }

        for (Task task : taskList) {
            try {
                quartzManager.deleteJob(task);
            } catch (SchedulerException e) {
                e.printStackTrace();
                return new BaseResult(ResponseCode.DELETE_ERROR);
            }
        }
        taskDao.batchDelete(ids);
        return new BaseResult();
    }

    @Override
    public BaseResult run(Integer id) {
        Task task = taskDao.getById(id);
        if (task == null) {
            return new BaseResult(ResponseCode.FAIL);
        }
        // 如果任务状态为关闭状态则不能立即执行
        if (TaskStatusEnum.STOP.getCode() == task.getJobStatus()) {
            return new BaseResult(ResponseCode.RUN_TASK_BEFORE_OPERATING);
        }
        try {
            quartzManager.runJobNow(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return new BaseResult(ResponseCode.FAIL);
        }
        return new BaseResult();
    }

    @Override
    public BaseResult changeStatus(Integer id, Integer jobStatus) {
        Task task = taskDao.getById(id);
        if (task == null) {
            return new BaseResult(ResponseCode.UPDATE_ERROR);
        }
        try {
            // 将任务状态设为相反状态
            if (TaskStatusEnum.STOP.getCode() == jobStatus) {
                quartzManager.deleteJob(task);
                task.setJobStatus(TaskStatusEnum.STOP.getCode());
            } else {
                quartzManager.addJob(task);
                task.setJobStatus(TaskStatusEnum.RUNNING.getCode());
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            return new BaseResult(ResponseCode.UPDATE_ERROR);
        }
        taskDao.update(task);
        return new BaseResult();
    }

    @Override
    public BaseResult updateCron(Integer id) {
        Task task = taskDao.getById(id);
        if (task == null) {
            return new BaseResult(ResponseCode.UPDATE_ERROR);
        }
        // 如果任务状态为开启状态则不能立即执行
        if (TaskStatusEnum.RUNNING.getCode() == task.getJobStatus()) {
            try {
                quartzManager.updateJobCron(task);
            } catch (SchedulerException e) {
                e.printStackTrace();
                return new BaseResult(ResponseCode.UPDATE_ERROR);
            }
        }
        taskDao.update(task);
        return new BaseResult();
    }

    @Override
    public boolean initJob() {
        // 获取任务信息数据
        List<Task> taskList = taskDao.getRunningTask();
        try {
            for (Task task : taskList) {
                // 初始化状态为开启的任务
                if (TaskStatusEnum.RUNNING.getCode() == task.getJobStatus()) {
                    quartzManager.addJob(task);
                }
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
